From 18626a5fa6e9b71453b6a34227bace72761a1c60 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Mon, 23 Feb 2004 13:57:02 +0000 Subject: [PATCH] bitkeeper revision 1.737 (403a06aeivKFHIf1N0Wp-yJEFUDIrw) serial.h: new file Many files: Rewritten serial and console I/O for Xen. New command-line options (see the docs). ser_baud is deprecated. Xeno-HOWTO.txt: Rename: docs/Xeno-1.2-HOWTO.txt -> docs/Xeno-HOWTO.txt serial.c: Rename: xen/drivers/char/xen_serial.c -> xen/drivers/char/serial.c --- .rootkeys | 5 +- README.CD | 30 +- docs/{Xeno-1.2-HOWTO.txt => Xeno-HOWTO.txt} | 28 +- xen/arch/i386/boot/boot.S | 20 +- xen/arch/i386/nmi.c | 1 - xen/arch/i386/pdb-stub.c | 71 ++-- xen/arch/i386/setup.c | 10 +- xen/common/domain.c | 6 +- xen/common/kernel.c | 250 +++++------- xen/common/keyhandler.c | 37 +- xen/common/memory.c | 4 +- xen/drivers/char/serial.c | 398 ++++++++++++++++++++ xen/drivers/char/xen_serial.c | 206 ---------- xen/include/xeno/config.h | 2 +- xen/include/xeno/console.h | 32 +- xen/include/xeno/lib.h | 1 - xen/include/xeno/serial.h | 39 ++ 17 files changed, 660 insertions(+), 480 deletions(-) rename docs/{Xeno-1.2-HOWTO.txt => Xeno-HOWTO.txt} (88%) create mode 100644 xen/drivers/char/serial.c delete mode 100644 xen/drivers/char/xen_serial.c create mode 100644 xen/include/xeno/serial.h diff --git a/.rootkeys b/.rootkeys index bd163ff5e1..15ed120cc5 100644 --- a/.rootkeys +++ b/.rootkeys @@ -8,7 +8,7 @@ 3f69d8abYB1vMyD_QVDvzxy5Zscf1A TODO 3f9e7d53iC47UnlfORp9iC1vai6kWw docs/Makefile 40083bb4LVQzRqA3ABz0__pPhGNwtA docs/VBD-HOWTO.txt -4021053fmeFrEyPHcT8JFiDpLNgtHQ docs/Xeno-1.2-HOWTO.txt +4021053fmeFrEyPHcT8JFiDpLNgtHQ docs/Xeno-HOWTO.txt 3f9e7d60PWZJeVh5xdnk0nLUdxlqEA docs/eps/xenlogo.eps 3f9e7d63lTwQbp2fnx7yY93epWS-eQ docs/figs/dummy 3f9e7d564bWFB-Czjv1qdmE6o0GqNg docs/interface.tex @@ -167,8 +167,8 @@ 3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile 3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c 3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile +3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c 3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c -3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/xen_serial.c 3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile 3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c 3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h @@ -479,6 +479,7 @@ 4006e65fWMwLqcocgik6wbF0Eeh0Og xen/include/xeno/rbtree.h 3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xeno/reboot.h 3ddb79c0LzqqS0LhAQ50ekgj4oGl7Q xen/include/xeno/sched.h +403a06a7H0hpHcKpAiDe5BPnaXWTlA xen/include/xeno/serial.h 3ddb79c0VDeD-Oft5eNfMneTU3D1dQ xen/include/xeno/skbuff.h 3ddb79c14dXIhP7C2ahnoD08K90G_w xen/include/xeno/slab.h 3ddb79c09xbS-xxfKxuV3JETIhBzmg xen/include/xeno/smp.h diff --git a/README.CD b/README.CD index 8bbd212c09..e9d172f268 100644 --- a/README.CD +++ b/README.CD @@ -76,7 +76,7 @@ sequentially for subsequent domains unless told otherwise. After selecting the kernel to boot, stand back and watch Xen boot, closely followed by "domain 0" running the XenoLinux kernel. The boot messages can also sent to the serial line by specifying the baud rate -on the Xen cmdline (e.g., 'ser_baud=9600'); this can be very useful +on the Xen cmdline (e.g., 'com1=9600,8n1'); this can be very useful for debugging should anything important scroll off the screen. Xen's startup messages will look quite familiar as much of the hardware initialisation (SMP boot, apic setup) and device drivers are derived @@ -329,7 +329,31 @@ that may be able to help diagnose problems: ifname=dummy Don't use any network interface. - ser_baud=xxx Enable serial I/O and set the baud rate (COM1) + com1=,DPS[,,] + com2=,DPS[,,] + Xen supports up to two 16550-compatible serial ports. + For example: 'com1=9600,8n1,0x408,5' maps COM1 to a + 9600-baud port, 8 data bits, no parity, 1 stop bit, + I/O port base 0x408, IRQ 5. + If the I/O base and IRQ are standard (com1:0x3f8,4; + com2:0x2f8,3) then they need not be specified. + + console= + Specify the destination for Xen console I/O. + This is a comma-separated list of, for example: + vga: use VGA console and allow keyboard input + com1: use serial port com1 + com2H: use serial port com2. Transmitted chars will + have the MSB set. Received chars must have + MSB set. + com2L: use serial port com2. Transmitted chars will + have the MSB cleared. Received chars must + have MSB cleared. + The latter two examples allow a single port to be + shared by two subsystems (eg. console and + debugger). Sharing is controlled by MSB of each + transmitted/received character. + [NB. Default for this option is 'com1,tty'] dom0_mem=xxx Set the initial amount of memory for domain0. @@ -405,7 +429,7 @@ config file. A typical Grub menu option might look like: title Xen / XenoLinux 2.4.22 - kernel /boot/image.gz dom0_mem=131072 ser_baud=115200 noht + kernel /boot/image.gz dom0_mem=131072 com1=115200,8n1 noht module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0 The first line specifies which Xen image to use, and what command line diff --git a/docs/Xeno-1.2-HOWTO.txt b/docs/Xeno-HOWTO.txt similarity index 88% rename from docs/Xeno-1.2-HOWTO.txt rename to docs/Xeno-HOWTO.txt index fb89fe6b37..e30c74794d 100644 --- a/docs/Xeno-1.2-HOWTO.txt +++ b/docs/Xeno-HOWTO.txt @@ -156,7 +156,7 @@ the Grub configuration file '/boot/grub/menu.lst'. A typical Grub menu option might look like: title Xen 1.2 / XenoLinux 2.4.24 - kernel /boot/xen.gz dom0_mem=131072 ser_baud=115200 noht + kernel /boot/xen.gz dom0_mem=131072 com1=115200,8n1 noht module /boot/xenolinux.gz root=/dev/sda4 ro console=tty0 The first line specifies which Xen image to use, and what command line @@ -197,7 +197,31 @@ The following is a list of command line arguments to pass to Xen: ifname=dummy Don't use any network interface. - ser_baud=xxx Enable serial I/O and set the baud rate. + com1=,DPS[,,] + com2=,DPS[,,] + Xen supports up to two 16550-compatible serial ports. + For example: 'com1=9600,8n1,0x408,5' maps COM1 to a + 9600-baud port, 8 data bits, no parity, 1 stop bit, + I/O port base 0x408, IRQ 5. + If the I/O base and IRQ are standard (com1:0x3f8,4; + com2:0x2f8,3) then they need not be specified. + + console= + Specify the destination for Xen console I/O. + This is a comma-separated list of, for example: + vga: use VGA console and allow keyboard input + com1: use serial port com1 + com2H: use serial port com2. Transmitted chars will + have the MSB set. Received chars must have + MSB set. + com2L: use serial port com2. Transmitted chars will + have the MSB cleared. Received chars must + have MSB cleared. + The latter two examples allow a single port to be + shared by two subsystems (eg. console and + debugger). Sharing is controlled by MSB of each + transmitted/received character. + [NB. Default for this option is 'com1,tty'] dom0_mem=xxx Set the maximum amount of memory for domain0. diff --git a/xen/arch/i386/boot/boot.S b/xen/arch/i386/boot/boot.S index f0e5a57c75..4d9204ce45 100644 --- a/xen/arch/i386/boot/boot.S +++ b/xen/arch/i386/boot/boot.S @@ -186,30 +186,14 @@ ignore_int: pushl $int_msg call SYMBOL_NAME(printf) 1: jmp 1b - pop %eax - popl %ds - popl %es - pop %edx - pop %ecx - pop %eax - iret - bad_cpu_msg: .asciz "Bad CPU type. Need P6+." ALIGN bad_cpu: -/* NB. We assume the UART is set up correctly. */ - mov $bad_cpu_msg,%esi -1: lodsb - test %al,%al - je 1f - push %eax - call putchar_serial - add $4,%esp - jmp 1b + pushl $bad_cpu_msg + call SYMBOL_NAME(printf) 1: jmp 1b - /*** STACK LOCATION ***/ diff --git a/xen/arch/i386/nmi.c b/xen/arch/i386/nmi.c index a2555752ae..16aace462d 100644 --- a/xen/arch/i386/nmi.c +++ b/xen/arch/i386/nmi.c @@ -276,7 +276,6 @@ void nmi_watchdog_tick (struct pt_regs * regs) { extern spinlock_t console_lock; extern void die(const char * str, struct pt_regs * regs, long err); - extern void putchar_serial(unsigned char c); int sum, cpu = smp_processor_id(); diff --git a/xen/arch/i386/pdb-stub.c b/xen/arch/i386/pdb-stub.c index f56abae004..87fb907fb8 100644 --- a/xen/arch/i386/pdb-stub.c +++ b/xen/arch/i386/pdb-stub.c @@ -5,6 +5,7 @@ #include #include #include +#include #define BUFMAX 400 @@ -27,8 +28,32 @@ static int pdb_info_thread = -1; static int pdb_stepping = 0; void pdb_put_packet (unsigned char *buffer, int ack); -void pdb_put_char (u_char c); -u_char pdb_get_char (); + +static int pdb_initialized = 0; +static int pdb_serhnd = -1; + +#define RX_SIZE 32 +#define RX_MASK(_i) ((_i)&(RX_SIZE-1)) +static unsigned int rx_cons = 0, rx_prod = 0; +static unsigned char rx_ring[RX_RING_SIZE]; + +static inline void pdb_put_char(unsigned char c) +{ + serial_putc(pdb_serhnd, c); +} + +static inline unsigned char pdb_get_char(void) +{ + while ( rx_cons == rx_prod ) + barrier(); + return rx_ring[RX_MASK(rx_cons++)]; +} + +static void pdb_rx_char(unsigned char c, struct pt_regs *regs) +{ + if ( (rx_prod - rx_cons) != RX_SIZE ) + rx_ring[RX_MASK(rx_prod++)] = c; +} static volatile int mem_err = 0; void set_mem_err (void) /* NOT USED YET... */ @@ -635,23 +660,6 @@ int pdb_bkpt_remove (unsigned long address) void breakpoint(void); -int pdb_initialized = 0; -int pdb_high_bit = 1; - -void pdb_put_char (u_char c) -{ - extern void debug_putchar(u_char); - u_char cc = pdb_high_bit ? c | 0x80 : c; - debug_putchar(cc); -} - -u_char pdb_get_char () -{ - extern u_char debug_getchar(); - u_char cc = debug_getchar(); - return cc & 0x7f; -} - /* send the packet in buffer. */ void pdb_put_packet (unsigned char *buffer, int ack) { @@ -821,35 +829,28 @@ void pdb_key_pressed(u_char key, void *dev_id, struct pt_regs *regs) void initialize_pdb() { extern char opt_pdb[]; - int pdb_com_port; /* Certain state must be initialised even when PDB will not be used. */ breakpoints.address = 0; INIT_LIST_HEAD(&breakpoints.list); pdb_stepping = 0; - if ( strncmp(opt_pdb, "com", 3) == 0 ) - { - extern void debug_set_com_port(int port); + if ( strcmp(opt_pdb, "none") == 0 ) + return; - pdb_com_port = opt_pdb[3] - '0'; /* error checking ? */ - debug_set_com_port(pdb_com_port); - pdb_high_bit = opt_pdb[4] == 'H' ? 1 : 0; - } - else + if ( (pdb_serhnd = parse_serial_handle(opt_pdb)) == -1 ) { - if ( strcmp(opt_pdb, "none") != 0 ) - printk ("pdb: unknown option\n"); + printk("Failed to initialise PDB on port %s\n", opt_pdb); return; } - printk("Initializing pervasive debugger (PDB) on serial port %d %s\n", - pdb_com_port, pdb_high_bit ? "(high bit enabled)" : ""); + serial_set_rx_handler(pdb_serhnd, pdb_rx_char); + + printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb); - /* ack any spurrious gdb packets */ - pdb_put_char ('+'); + /* Acknowledge any spurious GDB packets. */ + serial_putc(pdb_serhnd, '+'); - /* serial console */ add_key_handler('D', pdb_key_pressed, "enter pervasive debugger"); pdb_initialized = 1; diff --git a/xen/arch/i386/setup.c b/xen/arch/i386/setup.c index ee52629dee..ac2df96139 100644 --- a/xen/arch/i386/setup.c +++ b/xen/arch/i386/setup.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -316,7 +317,6 @@ void __init start_of_day(void) extern void net_init(void); extern void initialize_block_io(void); extern void initialize_keytable(); - extern void initialize_serial(void); extern void initialize_keyboard(void); extern int opt_nosmp, opt_watchdog, opt_noacpi, opt_ignorebiostables; extern int do_timer_lists_from_pit; @@ -406,6 +406,10 @@ void __init start_of_day(void) initialize_keytable(); /* call back handling for key codes */ + serial_init_stage2(); + initialize_keyboard(); /* setup keyboard (also for debugging) */ + initialize_pdb(); /* pervasive debugger */ + if ( !cpu_has_apic ) { do_timer_lists_from_pit = 1; @@ -427,10 +431,6 @@ void __init start_of_day(void) pci_init(); #endif do_initcalls(); - initialize_serial(); /* setup serial 'driver' (for debugging) */ - initialize_keyboard(); /* setup keyboard (also for debugging) */ - initialize_pdb(); /* pervasive debugger */ - if ( !setup_network_devices() ) panic("Must have a network device!\n"); net_init(); /* initializes virtual network system. */ diff --git a/xen/common/domain.c b/xen/common/domain.c index 4f45a88b91..42461c25be 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -787,9 +787,9 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params, } *dst = '\0'; - /* If this guy's getting the console we'd better let go. */ - if ( CONSOLE_ISOWNER(p) ) - opt_console = 0; + /* HACK: Give up the VGA console iff the Xenolinux DOM0 wants it. */ + if ( strstr(cmdline, "tty0") != NULL ) + vgacon_enabled = 0; /* Reinstate the caller's page tables. */ write_cr3_counted(pagetable_val(current->mm.pagetable)); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 3554ec5b17..42d6b1f46f 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -29,11 +29,15 @@ #include #include #include +#include kmem_cache_t *task_struct_cachep; static int xpos, ypos; -static volatile unsigned char *video; +static unsigned char *video = __va(0xB8000); + +int sercon_handle = -1; +int vgacon_enabled = 0; spinlock_t console_lock = SPIN_LOCK_UNLOCKED; @@ -43,15 +47,17 @@ struct e820entry { unsigned long type; /* type of memory segment */ }; -void init_vga(void); -void init_serial(void); +static void init_vga(void); void start_of_day(void); -/* opt_console: If true, Xen sends logging to the VGA console. */ -int opt_console = 1; +/* opt_console: comma-separated list of console outputs. */ +unsigned char opt_console[30] = "com1,vga"; /* opt_ser_baud: Baud rate at which logging is sent to COM1. */ /* NB. Default (0) means that serial I/O is disabled. */ +/* NB2. THIS OPTION IS DEPRECATED!! */ unsigned int opt_ser_baud = 0; +/* opt_com[12]: Config serial port with a string ,DPS,,. */ +unsigned char opt_com1[30] = "", opt_com2[30] = ""; /* opt_dom0_mem: Kilobytes of memory allocated to domain 0. */ unsigned int opt_dom0_mem = 16000; /* opt_ifname: Name of physical network interface to use. */ @@ -77,8 +83,10 @@ static struct { enum { OPT_IP, OPT_STR, OPT_UINT, OPT_BOOL } type; void *var; } opts[] = { - { "console", OPT_UINT, &opt_console }, + { "console", OPT_STR, &opt_console }, { "ser_baud", OPT_UINT, &opt_ser_baud }, + { "com1", OPT_STR, &opt_com1 }, + { "com2", OPT_STR, &opt_com2 }, { "dom0_mem", OPT_UINT, &opt_dom0_mem }, { "ifname", OPT_STR, &opt_ifname }, { "noht", OPT_BOOL, &opt_noht }, @@ -92,31 +100,16 @@ static struct { }; -void cmain (unsigned long magic, multiboot_info_t *mbi) +void cmain(unsigned long magic, multiboot_info_t *mbi) { struct task_struct *new_dom; dom0_createdomain_t dom0_params; unsigned long max_page; - unsigned char *cmdline; + unsigned char *cmdline, *p; module_t *mod; int i; - /* - * Note that serial output cannot be done properly until after - * command-line arguments have been parsed, and the required baud rate is - * known. Any messages before that will be output using the settings of - * the bootloader, for example. - */ - - if ( magic != MULTIBOOT_BOOTLOADER_MAGIC ) - { - init_vga(); - cls(); - printk("Invalid magic number: 0x%x\n", (unsigned)magic); - for ( ; ; ) ; - } - - /* Parse the command line. */ + /* Parse the command-line options. */ cmdline = (unsigned char *)(mbi->cmdline ? __va(mbi->cmdline) : NULL); if ( cmdline != NULL ) { @@ -158,10 +151,28 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) } } - init_serial(); + /* Backward compatibility with deprecated 'ser_baud=' cmdline option. */ + if ( opt_ser_baud != 0 ) + sprintf(opt_com1, "%u,8n1", opt_ser_baud); + + /* We initialise the serial devices very early so we can get debugging. */ + serial_init_stage1(); + + /* Where should console output go? */ + for ( p = opt_console; p != NULL; p = strchr(p, ',') ) + { + if ( *p == ',' ) + p++; + if ( strncmp(p, "com", 3) == 0 ) + sercon_handle = parse_serial_handle(p); + else if ( strncmp(p, "vga", 3) == 0 ) + vgacon_enabled = 1; + } + + /* Set up VGA console output, if it was enabled. */ init_vga(); - cls(); + /* HELLO WORLD --- start-of-day banner text. */ printk(XEN_BANNER); printk(" http://www.cl.cam.ac.uk/netos/xen\n"); printk(" University of Cambridge Computer Laboratory\n\n"); @@ -170,6 +181,16 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) XEN_COMPILE_BY, XEN_COMPILE_DOMAIN, XEN_COMPILER, XEN_COMPILE_DATE); + if ( opt_ser_baud != 0 ) + printk("**WARNING**: Xen option 'ser_baud=' is deprecated! " + "Use 'com1=' instead.\n"); + + if ( magic != MULTIBOOT_BOOTLOADER_MAGIC ) + { + printk("FATAL ERROR: Invalid magic number: 0x%08lx\n", magic); + for ( ; ; ) ; + } + /* We require memory and module information. */ if ( (mbi->flags & 9) != 9 ) { @@ -245,60 +266,20 @@ void cmain (unsigned long magic, multiboot_info_t *mbi) } -#define SERIAL_BASE 0x3f8 -#define RX_BUF 0 -#define TX_HOLD 0 -#define INT_ENABLE 1 -#define INT_IDENT 2 -#define DATA_FORMAT 3 -#define LINE_CTL 4 -#define LINE_STATUS 5 -#define LINE_IN 6 -#define DIVISOR_LO 0 -#define DIVISOR_HI 1 - -void init_serial(void) -{ - if ( !SERIAL_ENABLED ) - return; - - /* 'opt_ser_baud' baud, no parity, 1 stop bit, 8 data bits. */ - outb(0x83, SERIAL_BASE+DATA_FORMAT); - outb(115200/opt_ser_baud, SERIAL_BASE+DIVISOR_LO); - outb(0, SERIAL_BASE+DIVISOR_HI); - outb(0x03, SERIAL_BASE+DATA_FORMAT); - - /* DTR and RTS should both be high, to keep other end happy. */ - outb(0x02, SERIAL_BASE+LINE_CTL); - - /* No interrupts. */ - outb(0x00, SERIAL_BASE+INT_ENABLE); -} - - -#ifdef CONFIG_OUTPUT_SERIAL -void putchar_serial(unsigned char c) -{ - if ( !SERIAL_ENABLED ) - return; - if ( c == '\n' ) putchar_serial('\r'); - while ( !(inb(SERIAL_BASE+LINE_STATUS)&(1<<5)) ) barrier(); - outb(c, SERIAL_BASE+TX_HOLD); -} -#else -void putchar_serial(unsigned char c) {} -#endif - - -#ifdef CONFIG_OUTPUT_CONSOLE - /* VGA text (mode 3) definitions. */ #define COLUMNS 80 #define LINES 25 #define ATTRIBUTE 7 -#define VIDEO __va(0xB8000) -int detect_video(void *video_base) +/* Clear the screen and initialize VIDEO, XPOS and YPOS. */ +static void cls(void) +{ + memset(video, 0, COLUMNS * LINES * 2); + xpos = ypos = 0; + outw(10+(1<<(5+8)), 0x3d4); /* cursor off */ +} + +static int detect_video(void *video_base) { volatile u16 *p = (volatile u16 *)video_base; u16 saved1 = p[0], saved2 = p[1]; @@ -320,7 +301,7 @@ int detect_video(void *video_base) return video_found; } -int detect_vga(void) +static int detect_vga(void) { /* * Look at a number of well-known locations. Even if video is not at @@ -337,7 +318,7 @@ int detect_vga(void) } /* This is actually code from vgaHWRestore in an old version of XFree86 :-) */ -void init_vga(void) +static void init_vga(void) { /* The following VGA state was saved from a chip in text mode 3. */ static unsigned char regs[] = { @@ -357,13 +338,13 @@ void init_vga(void) int i, j = 0; volatile unsigned char tmp; - if ( !opt_console ) + if ( !vgacon_enabled ) return; if ( !detect_vga() ) { printk("No VGA adaptor detected!\n"); - opt_console = 0; + vgacon_enabled = 0; return; } @@ -391,26 +372,8 @@ void init_vga(void) tmp = inb(0x3da); outb(0x20, 0x3c0); -} - - -/* Clear the screen and initialize VIDEO, XPOS and YPOS. */ -void cls(void) -{ - int i; - if ( !opt_console ) - return; - - video = (unsigned char *) VIDEO; - - for (i = 0; i < COLUMNS * LINES * 2; i++) - *(video + i) = 0; - - xpos = 0; - ypos = 0; - - outw(10+(1<<(5+8)), 0x3d4); /* cursor off */ + cls(); } @@ -431,9 +394,9 @@ static void put_newline(void) } -void putchar_console(int c) +static void putchar_console(int c) { - if ( !opt_console ) + if ( !vgacon_enabled ) return; if ( c == '\n' ) @@ -442,54 +405,34 @@ void putchar_console(int c) } else { - *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; - *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; - - xpos++; - if (xpos >= COLUMNS) + video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF; + video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE; + if ( ++xpos >= COLUMNS ) put_newline(); } } -#else - -void init_vga(void) {} -void cls(void) {} -void putchar_console(int c) {} - -#endif - -#ifdef CONFIG_OUTPUT_CONSOLE_RING void putchar_console_ring(int c) { - if (console_ring.len < CONSOLE_RING_SIZE) + if ( console_ring.len < CONSOLE_RING_SIZE ) console_ring.buf[console_ring.len++] = (char)c; } -#else - -void putchar_console_ring(int c) {} - -#endif - - -static void putchar(int c) -{ - if ( (c != '\n') && ((c < 32) || (c > 126)) ) return; - putchar_serial(c); - putchar_console(c); - putchar_console_ring(c); -} - static inline void __putstr(const char *str) { - while ( *str ) putchar(*str++); + int c; + serial_puts(sercon_handle, str); + while ( (c = *str++) != '\0' ) + { + putchar_console(c); + putchar_console_ring(c); + } } -void printf (const char *fmt, ...) +void printf(const char *fmt, ...) { va_list args; char buf[128]; @@ -510,7 +453,7 @@ void printf (const char *fmt, ...) } spin_lock_irqsave(&console_lock, flags); - while ( *p ) putchar(*p++); + __putstr(p); spin_unlock_irqrestore(&console_lock, flags); } @@ -633,11 +576,12 @@ long do_console_write(char *str, unsigned int count) { #define SIZEOF_BUF 256 unsigned char safe_str[SIZEOF_BUF+1]; - unsigned char exported_str[SIZEOF_BUF+2]; - unsigned char dom_id[5]; + unsigned char single_line[SIZEOF_BUF+2]; + unsigned char line_header[30]; unsigned char *p; + unsigned char c; unsigned long flags; - int j; + int j; if ( count == 0 ) return 0; @@ -649,38 +593,32 @@ long do_console_write(char *str, unsigned int count) return -EFAULT; safe_str[count] = '\0'; + sprintf(line_header, "DOM%llu: ", current->domain); + p = safe_str; while ( *p != '\0' ) { j = 0; - spin_lock_irqsave(&console_lock, flags); - - __putstr("DOM"); - sprintf(dom_id, "%llu", current->domain); - __putstr(dom_id); - __putstr(": "); - - while ( (*p != '\0') && (*p != '\n') ) + while ( (c = *p++) != '\0' ) { - exported_str[j++] = *p; - putchar(*p); - p++; + if ( c == '\n' ) + break; + if ( (c < 32) || (c > 126) ) + continue; + single_line[j++] = c; } - if ( *p == '\n' ) - p++; + single_line[j++] = '\n'; + single_line[j++] = '\0'; - putchar('\n'); - + spin_lock_irqsave(&console_lock, flags); + __putstr(line_header); + __putstr(single_line); spin_unlock_irqrestore(&console_lock, flags); if ( current->domain != 0 ) - { - exported_str[j++] = '\n'; - exported_str[j++] = '\0'; - console_export(exported_str, j); - } + console_export(single_line, j); } return 0; diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index 0a99969113..06e2531773 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #define KEY_MAX 256 #define STR_MAX 64 @@ -18,21 +20,21 @@ void add_key_handler(u_char key, key_handler *handler, char *desc) int i; char *str; - if(key_table[key].handler != NULL) + if ( key_table[key].handler != NULL ) printk("Warning: overwriting handler for key 0x%x\n", key); key_table[key].handler = handler; str = key_table[key].desc; - for(i = 0; i < STR_MAX; i++) { - if(*desc) + for ( i = 0; i < STR_MAX; i++ ) + { + if ( *desc != '\0' ) *str++ = *desc++; - else break; + else + break; } - if (i == STR_MAX) + if ( i == STR_MAX ) key_table[key].desc[STR_MAX-1] = '\0'; - - return; } key_handler *get_key_handler(u_char key) @@ -40,42 +42,43 @@ key_handler *get_key_handler(u_char key) return key_table[key].handler; } +static void serial_rx(unsigned char c, struct pt_regs *regs) +{ + key_handler *handler; + if ( (handler = get_key_handler(c)) != NULL ) + (*handler)(c, NULL, regs); +} static void show_handlers(u_char key, void *dev_id, struct pt_regs *regs) { int i; printk("'%c' pressed -> showing installed handlers\n", key); - for(i=0; i < KEY_MAX; i++) - if(key_table[i].handler) + for ( i = 0; i < KEY_MAX; i++ ) + if ( key_table[i].handler != NULL ) printk(" key '%c' (ascii '%02x') => %s\n", (i<33 || i>126)?(' '):(i),i, key_table[i].desc); - return; } static void dump_registers(u_char key, void *dev_id, struct pt_regs *regs) { extern void show_registers(struct pt_regs *regs); - printk("'%c' pressed -> dumping registers\n", key); show_registers(regs); - return; } static void halt_machine(u_char key, void *dev_id, struct pt_regs *regs) { printk("'%c' pressed -> rebooting machine\n", key); machine_restart(NULL); - return; } static void kill_dom0(u_char key, void *dev_id, struct pt_regs *regs) { printk("'%c' pressed -> gracefully rebooting machine\n", key); kill_other_domain(0, 0); - return; } @@ -137,12 +140,12 @@ void audit_all_pages(u_char key, void *dev_id, struct pt_regs *regs); #endif -void initialize_keytable() +void initialize_keytable(void) { int i; /* first initialize key handler table */ - for(i = 0; i < KEY_MAX; i++) + for ( i = 0; i < KEY_MAX; i++ ) key_table[i].handler = (key_handler *)NULL; /* setup own handlers */ @@ -160,4 +163,6 @@ void initialize_keytable() add_key_handler('m', reaudit_pages, "re-audit pages"); add_key_handler('M', audit_all_pages, "audit all pages"); #endif + + serial_set_rx_handler(sercon_handle, serial_rx); } diff --git a/xen/common/memory.c b/xen/common/memory.c index e7caf7a60b..bc1a5b530b 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -140,9 +140,9 @@ #include #ifndef NDEBUG -#define MEM_LOG(_f, _a...) \ +#define MEM_LOG(_f, _a...) \ printk("DOM%llu: (file=memory.c, line=%d) " _f "\n", \ - current->domain, __LINE__, ## _a ) + current->domain , __LINE__ , ## _a ) #else #define MEM_LOG(_f, _a...) ((void)0) #endif diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c new file mode 100644 index 0000000000..b936da4110 --- /dev/null +++ b/xen/drivers/char/serial.c @@ -0,0 +1,398 @@ +/****************************************************************************** + * serial.c + * + * Driver for 16550-series UARTs. This driver is to be kept within Xen as + * it permits debugging of seriously-toasted machines (e.g., in situations + * where a device driver within a guest OS would be inaccessible). + * + * Copyright (c) 2003-2004, K A Fraser + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ +#define RBR 0x00 /* receive buffer */ +#define THR 0x00 /* transmit holding */ +#define IER 0x01 /* interrupt enable */ +#define IIR 0x02 /* interrupt identity */ +#define FCR 0x02 /* FIFO control */ +#define LCR 0x03 /* line control */ +#define MCR 0x04 /* Modem control */ +#define LSR 0x05 /* line status */ +#define MSR 0x06 /* Modem status */ +#define DLL 0x00 /* divisor latch (ls) ( DLAB=1) */ +#define DLM 0x01 /* divisor latch (ms) ( DLAB=1) */ + +/* Interrupt Enable Register */ +#define IER_ERDAI 0x01 /* rx data recv'd */ +#define IER_ETHREI 0x02 /* tx reg. empty */ +#define IER_ELSI 0x04 /* rx line status */ +#define IER_EMSI 0x08 /* MODEM status */ + +/* FIFO control register */ +#define FCR_ENABLE 0x01 /* enable FIFO */ +#define FCR_CLRX 0x02 /* clear Rx FIFO */ +#define FCR_CLTX 0x04 /* clear Tx FIFO */ +#define FCR_DMA 0x10 /* enter DMA mode */ +#define FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */ +#define FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */ +#define FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */ +#define FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */ + +/* Line control register */ +#define LCR_DLAB 0x80 /* Divisor Latch Access */ + +/* Modem Control Register */ +#define MCR_DTR 0x01 /* Data Terminal Ready */ +#define MCR_RTS 0x02 /* Request to Send */ +#define MCR_OUT2 0x08 /* OUT2: interrupt mask */ + +/* Line Status Register */ +#define LSR_DR 0x01 /* Data ready */ +#define LSR_OE 0x02 /* Overrun */ +#define LSR_PE 0x04 /* Parity error */ +#define LSR_FE 0x08 /* Framing error */ +#define LSR_BI 0x10 /* Break */ +#define LSR_THRE 0x20 /* Xmit hold reg empty */ +#define LSR_TEMT 0x40 /* Xmitter empty */ +#define LSR_ERR 0x80 /* Error */ + +/* These parity settings can be ORed directly into the LCR. */ +#define PARITY_NONE (0<<3) +#define PARITY_ODD (1<<3) +#define PARITY_EVEN (3<<3) +#define PARITY_MARK (5<<3) +#define PARITY_SPACE (7<<3) + +typedef struct { + int baud, data_bits, parity, stop_bits, io_base, irq; + serial_rx_fn rx_lo, rx_hi, rx; + spinlock_t lock; +} uart_t; + +static uart_t com[2] = { + { 0, 0, 0, 0, 0x3f8, 4, + NULL, NULL, NULL, + SPIN_LOCK_UNLOCKED }, + { 0, 0, 0, 0, 0x2f8, 3, + NULL, NULL, NULL, + SPIN_LOCK_UNLOCKED } +}; + +#define UART_ENABLED(_u) ((_u)->baud != 0) +#define DISABLE_UART(_u) ((_u)->baud = 0) + + +/*********************** + * PRIVATE FUNCTIONS + */ + +static void uart_rx(uart_t *uart, struct pt_regs *regs) +{ + unsigned char c; + + if ( !UART_ENABLED(uart) ) + return; + + /* + * No need for the uart spinlock here. Only the uart's own interrupt + * handler will read from the RBR and the handler isn't reentrant. + */ + while ( inb(uart->io_base + LSR) & LSR_DR ) + { + c = inb(uart->io_base + RBR); + if ( uart->rx != NULL ) + uart->rx(c, regs); + else if ( (c & 0x80) && (uart->rx_hi != NULL) ) + uart->rx_hi(c&0x7f, regs); + else if ( !(c & 0x80) && (uart->rx_lo != NULL) ) + uart->rx_lo(c&0x7f, regs); + } +} + +static void serial_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + uart_rx((uart_t *)dev_id, regs); +} + +static inline void __serial_putc(uart_t *uart, int handle, unsigned char c) +{ + if ( (c == '\n') && (handle & SERHND_COOKED) ) + __serial_putc(uart, handle, '\r'); + + if ( handle & SERHND_HI ) + c |= 0x80; + else if ( handle & SERHND_LO ) + c &= ~0x7f; + + while ( !(inb(uart->io_base + LSR) & LSR_THRE) ) + barrier(); + + outb(c, uart->io_base + THR); +} + +#define PARSE_ERR(_f, _a...) \ + do { \ + printk( "ERROR: " _f "\n" , ## _a ); \ + DISABLE_UART(uart); \ + return; \ +} while ( 0 ) + +static void parse_port_config(char *conf, uart_t *uart) +{ + if ( *conf == '\0' ) + return; + + uart->baud = simple_strtol(conf, &conf, 10); + if ( (uart->baud < 1200) || (uart->baud > 115200) ) + PARSE_ERR("Baud rate %d outside supported range.", uart->baud); + + if ( *conf != ',' ) + PARSE_ERR("Missing data/parity/stop specifiers."); + + conf++; + + uart->data_bits = simple_strtol(conf, &conf, 10); + if ( (uart->data_bits < 5) || (uart->data_bits > 8) ) + PARSE_ERR("%d data bits are unsupported.", uart->data_bits); + + switch ( *conf ) + { + case 'n': + uart->parity = PARITY_NONE; + break; + case 'o': + uart->parity = PARITY_ODD; + break; + case 'e': + uart->parity = PARITY_EVEN; + break; + case 'm': + uart->parity = PARITY_MARK; + break; + case 's': + uart->parity = PARITY_SPACE; + break; + + default: + PARSE_ERR("Invalid parity specifier '%c'.", *conf); + } + + conf++; + + uart->stop_bits = simple_strtol(conf, &conf, 10); + if ( (uart->stop_bits < 1) || (uart->stop_bits > 2) ) + PARSE_ERR("%d stop bits are unsupported.", uart->stop_bits); + + if ( *conf == ',' ) + { + conf++; + + uart->io_base = simple_strtol(conf, &conf, 0); + if ( (uart->io_base <= 0x0000) || (uart->io_base > 0xfff0) ) + PARSE_ERR("I/O port base 0x%x is outside the supported range.", + uart->io_base); + + if ( *conf != ',' ) + PARSE_ERR("Missing IRQ specifier."); + + conf++; + + uart->irq = simple_strtol(conf, &conf, 10); + if ( (uart->irq <= 0) || (uart->irq >= 32) ) + PARSE_ERR("IRQ %d is outside the supported range.", uart->irq); + } +} + +static void uart_config_stage1(uart_t *uart) +{ + unsigned char lcr; + + if ( !UART_ENABLED(uart) ) + return; + + lcr = (uart->data_bits - 5) | ((uart->stop_bits - 1) << 2) | uart->parity; + + /* No interrupts. */ + outb(0, uart->io_base + IER); + + /* Line control and baud-rate generator. */ + outb(lcr | LCR_DLAB, uart->io_base + LCR); + outb(115200/uart->baud, uart->io_base + DLL); /* baud lo */ + outb(0, uart->io_base + DLM); /* baud hi */ + outb(lcr, uart->io_base + LCR); /* parity, data, stop */ + + /* No flow ctrl: DTR and RTS are both wedged high to keep remote happy. */ + outb(MCR_DTR | MCR_RTS, uart->io_base + MCR); + + /* Enable and clear the FIFOs. Set a large trigger threshold. */ + outb(FCR_ENABLE | FCR_CLRX | FCR_CLTX | FCR_TRG14, uart->io_base + FCR); +} + +static void uart_config_stage2(uart_t *uart) +{ + int rc; + + if ( !UART_ENABLED(uart) ) + return; + + rc = request_irq(uart->irq, + serial_interrupt, + SA_NOPROFILE, + "serial", + uart); + if ( rc != 0 ) + printk("ERROR: Failed to allocate serial IRQ %d\n", uart->irq); + + /* For sanity, clear the receive FIFO. */ + outb(FCR_ENABLE | FCR_CLRX | FCR_TRG14, uart->io_base + FCR); + + /* Master interrupt enable; also keep DTR/RTS asserted. */ + outb(MCR_OUT2 | MCR_DTR | MCR_RTS, uart->io_base + MCR); + + /* Enable receive interrupts. */ + outb(IER_ERDAI, uart->io_base + IER); +} + + +/*********************** + * PUBLIC FUNCTIONS + */ + +void serial_init_stage1(void) +{ + extern unsigned char opt_com1[], opt_com2[]; + + parse_port_config(opt_com1, &com[0]); + parse_port_config(opt_com2, &com[1]); + + uart_config_stage1(&com[0]); + uart_config_stage1(&com[1]); +} + +void serial_init_stage2(void) +{ + uart_config_stage2(&com[0]); + uart_config_stage2(&com[1]); +} + +int parse_serial_handle(char *conf) +{ + int handle; + + /* Silently fail if user has explicitly requested no serial I/O. */ + if ( strcmp(conf, "none") == 0 ) + return -1; + + if ( strncmp(conf, "com", 3) != 0 ) + goto fail; + + switch ( conf[3] ) + { + case '1': + handle = 0; + break; + case '2': + handle = 1; + break; + default: + goto fail; + } + + if ( !UART_ENABLED(&com[handle]) ) + { + printk("ERROR: cannot use unconfigured serial port COM%d\n", handle+1); + return -1; + } + + if ( conf[4] == 'H' ) + handle |= SERHND_HI; + else if ( conf[4] == 'L' ) + handle |= SERHND_LO; + + handle |= SERHND_COOKED; + + return handle; + + fail: + printk("ERROR: bad serial-interface specification '%s'\n", conf); + return -1; +} + +void serial_set_rx_handler(int handle, serial_rx_fn fn) +{ + uart_t *uart = &com[handle & SERHND_IDX]; + unsigned long flags; + + if ( handle == -1 ) + return; + + spin_lock_irqsave(&uart->lock, flags); + + if ( uart->rx != NULL ) + goto fail; + + if ( handle & SERHND_LO ) + { + if ( uart->rx_lo != NULL ) + goto fail; + uart->rx_lo = fn; + } + else if ( handle & SERHND_HI ) + { + if ( uart->rx_hi != NULL ) + goto fail; + uart->rx_hi = fn; + } + else + { + if ( (uart->rx_hi != NULL) || (uart->rx_lo != NULL) ) + goto fail; + uart->rx = fn; + } + + spin_unlock_irqrestore(&uart->lock, flags); + return; + + fail: + spin_unlock_irqrestore(&uart->lock, flags); + printk("ERROR: Conflicting receive handlers for COM%d\n", + handle & SERHND_IDX); +} + +void serial_putc(int handle, unsigned char c) +{ + uart_t *uart = &com[handle & SERHND_IDX]; + unsigned long flags; + + if ( handle == -1 ) + return; + + spin_lock_irqsave(&uart->lock, flags); + + __serial_putc(uart, handle, c); + + spin_unlock_irqrestore(&uart->lock, flags); +} + +void serial_puts(int handle, const unsigned char *s) +{ + uart_t *uart = &com[handle & SERHND_IDX]; + unsigned long flags; + + if ( handle == -1 ) + return; + + spin_lock_irqsave(&uart->lock, flags); + + while ( *s != '\0' ) + __serial_putc(uart, handle, *s++); + + spin_unlock_irqrestore(&uart->lock, flags); +} diff --git a/xen/drivers/char/xen_serial.c b/xen/drivers/char/xen_serial.c deleted file mode 100644 index 41e411d84b..0000000000 --- a/xen/drivers/char/xen_serial.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include /* this has request_irq() proto for some reason */ -#include -#include -#include -#include - -/* Register offsets */ -#define NS16550_RBR 0x00 /* receive buffer */ -#define NS16550_THR 0x00 /* transmit holding */ -#define NS16550_IER 0x01 /* interrupt enable */ -#define NS16550_IIR 0x02 /* interrupt identity */ -#define NS16550_FCR 0x02 /* FIFO control */ -#define NS16550_LCR 0x03 /* line control */ -#define NS16550_MCR 0x04 /* MODEM control */ -#define NS16550_LSR 0x05 /* line status */ -#define NS16550_MSR 0x06 /* MODEM status */ -#define NS16550_SCR 0x07 /* scratch */ -#define NS16550_DDL 0x00 /* divisor latch (ls) ( DLAB=1) */ -#define NS16550_DLM 0x01 /* divisor latch (ms) ( DLAB=1) */ - -/* Interrupt enable register */ -#define NS16550_IER_ERDAI 0x01 /* rx data recv'd */ -#define NS16550_IER_ETHREI 0x02 /* tx reg. empty */ -#define NS16550_IER_ELSI 0x04 /* rx line status */ -#define NS16550_IER_EMSI 0x08 /* MODEM status */ - -/* FIFO control register */ -#define NS16550_FCR_ENABLE 0x01 /* enable FIFO */ -#define NS16550_FCR_CLRX 0x02 /* clear Rx FIFO */ -#define NS16550_FCR_CLTX 0x04 /* clear Tx FIFO */ -#define NS16550_FCR_DMA 0x10 /* enter DMA mode */ -#define NS16550_FCR_TRG1 0x00 /* Rx FIFO trig lev 1 */ -#define NS16550_FCR_TRG4 0x40 /* Rx FIFO trig lev 4 */ -#define NS16550_FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */ -#define NS16550_FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */ - -/* MODEM control register */ -#define NS16550_MCR_DTR 0x01 /* Data Terminal Ready */ -#define NS16550_MCR_RTS 0x02 /* Request to Send */ -#define NS16550_MCR_OUT1 0x04 /* OUT1: unused */ -#define NS16550_MCR_OUT2 0x08 /* OUT2: interrupt mask */ -#define NS16550_MCR_LOOP 0x10 /* Loop */ - -#define LSR_DR 0x01 /* Data ready */ -#define LSR_OE 0x02 /* Overrun */ -#define LSR_PE 0x04 /* Parity error */ -#define LSR_FE 0x08 /* Framing error */ -#define LSR_BI 0x10 /* Break */ -#define LSR_THRE 0x20 /* Xmit holding register empty */ -#define LSR_TEMT 0x40 /* Xmitter empty */ -#define LSR_ERR 0x80 /* Error */ - -#define SERIAL_COM1 0x3f8 -#define SERIAL_COM2 0x2f8 - -void initialize_serial_port(int base); - -int serial_com_base = SERIAL_COM1; -int debug_com_base = SERIAL_COM1; - -static int serial_echo = 0; /* default is not to echo; change with '~' */ - -void toggle_echo(u_char key, void *dev_id, struct pt_regs *regs) -{ - serial_echo = !serial_echo; -} - -void debug_set_com_port(int port) -{ - debug_com_base = port == 1 ? SERIAL_COM1 : SERIAL_COM2; - if (port == 2) initialize_serial_port(SERIAL_COM2); -} - -int debug_testchar() /* character available? */ -{ - return (inb(debug_com_base + NS16550_LSR) & LSR_DR); -} - -u_char debug_getchar() -{ - while (! (inb(debug_com_base + NS16550_LSR) & LSR_DR));/* wait for char */ - return inb(debug_com_base + NS16550_RBR); -} - -void debug_putch(u_char c) -{ - while (! (inb(debug_com_base + NS16550_LSR) & LSR_THRE)); - /* wait for idle */ - outb(c, debug_com_base + NS16550_RBR); -} - -void debug_putchar(u_char c) -{ - debug_putch(c); - if (c == '\n') debug_putch('\r'); -} - - - -int serial_testchar() /* character available? */ -{ - return (inb(serial_com_base + NS16550_LSR) & LSR_DR); -} - -u_char serial_getchar() -{ - while (! (inb(serial_com_base + NS16550_LSR) & LSR_DR));/* wait for char */ - return inb(serial_com_base + NS16550_RBR); -} - -void serial_putch(u_char c) -{ - while (! (inb(serial_com_base + NS16550_LSR) & LSR_THRE)); - /* wait for idle */ - outb(c, serial_com_base + NS16550_RBR); -} - -void serial_putchar(u_char c) -{ - serial_putch(c); - if ( c == '\n' ) - serial_putch('\r'); -} - -static spinlock_t serial_lock; - -static void serial_rx_int(int irq, void *dev_id, struct pt_regs *regs) -{ - u_char c; - key_handler *handler; - unsigned long flags; - - spin_lock_irqsave(&serial_lock, flags); - - while ( serial_testchar() ) - { - c = serial_getchar(); - - if ( c & 0x80 ) - { - pdb_serial_input(c & 0x7f, regs); - } - else - { - if ( (handler = get_key_handler(c)) != NULL ) - (*handler)(c, dev_id, regs); - - if ( serial_echo ) - serial_putch(c); - } - } - - spin_unlock_irqrestore(&serial_lock, flags); -} - -void initialize_serial() -{ - if ( !SERIAL_ENABLED ) - return; - - spin_lock_init(&serial_lock); - - /* setup key handler */ - add_key_handler('~', toggle_echo, "toggle serial echo"); - - initialize_serial_port(SERIAL_COM1); -} - -/* warning: no protection against duplicate initialization */ -void initialize_serial_port(int base) -{ - int rc; - - /* This assumes we have a 16550. It's pretty darned likely really! */ - /* Clear FIFOs, enable, trigger at 1 byte */ - outb(NS16550_FCR_TRG1 | NS16550_FCR_ENABLE | - NS16550_FCR_CLRX | NS16550_FCR_CLTX, - base + NS16550_FCR); - - /* Enable receive interrupts. Also remember to keep DTR/RTS asserted. */ - outb(NS16550_MCR_OUT2|NS16550_MCR_DTR|NS16550_MCR_RTS, - base + NS16550_MCR); - outb(NS16550_IER_ERDAI, - base + NS16550_IER ); - - switch(base) - { - case SERIAL_COM1 : - { - if( (rc = request_irq(4, serial_rx_int, SA_NOPROFILE, "serial 1", 0)) ) - printk("initialize_serial: failed to get IRQ4, rc=%d\n", rc); - break; - } - case SERIAL_COM2 : - { - if( (rc = request_irq(3, serial_rx_int, SA_NOPROFILE, "serial 2", 0)) ) - printk("initialize_serial: failed to get IRQ3, rc=%d\n", rc); - break; - } - default : - { - printk("initialize_serial: unknown serial base: 0x%d\n", base); - } - } -} diff --git a/xen/include/xeno/config.h b/xen/include/xeno/config.h index 6dc740405d..35cdd22ee4 100644 --- a/xen/include/xeno/config.h +++ b/xen/include/xeno/config.h @@ -147,7 +147,7 @@ #ifndef NDEBUG #define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ - __FILE__, __LINE__, ## _a) + __FILE__ , __LINE__ , ## _a ) #define STACK_GUARD #else #define DPRINTK(_f, _a...) ((void)0) diff --git a/xen/include/xeno/console.h b/xen/include/xeno/console.h index 375c4b2215..d68aa893bb 100644 --- a/xen/include/xeno/console.h +++ b/xen/include/xeno/console.h @@ -14,38 +14,12 @@ * who gets the PS/2 keyboard/mouse events */ +extern int sercon_handle; +extern int vgacon_enabled; + #define CONSOLE_ISOWNER(p) (p->domain == 0) #define CONSOLE_OWNER (find_domain_by_id(0)) - -/* - * Xen output redirection (in common/kernel.c) - * - * This is coarsely done right now - - * - a boot-time option for console output - * - a compile-time option for serial output and console output - * - * Really, when starting up a guest os with console privilege, we should: - * - reset the video to a known state - * - stop sending characters (clear 'opt_console') - * - allow the guest os access to the video RAM area and keyboard - * Similarly, when stopping that guest os, we should: - * - stop allowing the guest os access to video RAM - * - reset the video to a known state - * - start sending it console output again (if we so desire) - * - * Resetting the video to a known state has not been explored yet, although - * Xen resets to a VGA text mode at start of day. Also, the notion of - * privileges for guest os's (e.g. console privilege) has not been explored - * yet, so this will do for now. - */ - -#define CONFIG_OUTPUT_SERIAL 1 -#define CONFIG_OUTPUT_CONSOLE 1 -#define CONFIG_OUTPUT_CONSOLE_RING 1 - -extern int opt_console; - #define CONSOLE_RING_SIZE 16392 #define CONSOLE_RING_CLEAR 1 diff --git a/xen/include/xeno/lib.h b/xen/include/xeno/lib.h index 8cad54f9d1..c3fe557974 100644 --- a/xen/include/xeno/lib.h +++ b/xen/include/xeno/lib.h @@ -36,7 +36,6 @@ unsigned char *quad_to_str(unsigned long q, unsigned char *s); /* kernel.c */ #define printk printf void printf (const char *format, ...); -void cls(void); void panic(const char *format, ...); /* vsprintf.c */ diff --git a/xen/include/xeno/serial.h b/xen/include/xeno/serial.h new file mode 100644 index 0000000000..c24f0c665f --- /dev/null +++ b/xen/include/xeno/serial.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * serial.h + * + * Driver for 16550-series UARTs. This driver is to be kept within Xen as + * it permits debugging of seriously-toasted machines (e.g., in situations + * where a device driver within a guest OS would be inaccessible). + * + * Copyright (c) 2003-2004, K A Fraser + */ + +#ifndef __XEN_SERIAL_H__ +#define __XEN_SERIAL_H__ + +#include + +/* 'Serial handles' are comprise the following fields. */ +#define SERHND_IDX (1<<0) /* COM1 or COM2? */ +#define SERHND_HI (1<<1) /* Mux/demux each transferred char by MSB. */ +#define SERHND_LO (1<<2) /* Ditto, except that the MSB is cleared. */ +#define SERHND_COOKED (1<<3) /* Newline/carriage-return translation? */ + +/* Two-stage initialisation (before/after IRQ-subsystem initialisation). */ +void serial_init_stage1(void); +void serial_init_stage2(void); + +/* Takes a config string and creates a numeric handle on the COM port. */ +int parse_serial_handle(char *conf); + +/* Register a character-receive hook on the specified COM port. */ +typedef void (*serial_rx_fn)(unsigned char, struct pt_regs *); +void serial_set_rx_handler(int handle, serial_rx_fn fn); + +/* Transmit a single character via the specified COM port. */ +void serial_putc(int handle, unsigned char c); + +/* Transmit a NULL-terminated string via the specified COM port. */ +void serial_puts(int handle, const unsigned char *s); + +#endif /* __XEN_SERIAL_H__ */ -- 2.30.2